﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Windows.Forms;
using Global.Interfaces.Server;
using System.ServiceModel.PeerResolvers;
using System.Security.Cryptography.X509Certificates;
using Server.Service;
using System.Configuration;

namespace Server
{
    public partial class ServerForm : Form, IView
    {
        private ServiceHost _host;
        private Uri _baseAddress;
        private CustomBinding _binding;
        private string _address;
        private Uri _mexAddress;
        private CustomPeerResolverService _crs;
        private ServiceHost _customResolver;
        private IsMessengerServer _serverInstance;

        public ServerForm()
        {
            InitializeComponent();

            var netTcpBinding = new NetTcpBinding();
            netTcpBinding.Security.Mode = SecurityMode.Transport;
            netTcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
            netTcpBinding.ReceiveTimeout = new TimeSpan(0, 1, 0);
            netTcpBinding.SendTimeout = new TimeSpan(0, 1, 0);
            _binding = new CustomBinding(netTcpBinding);
            _address = "sMessengerServer";

            _baseAddress = new Uri(ConfigurationSettings.AppSettings["baseAddress"]);
            _mexAddress = new Uri(ConfigurationSettings.AppSettings["mexAddress"]);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            _serverInstance = new sMessengerServer(this);

            btnStart.Enabled = false;
            _host = new ServiceHost(_serverInstance, _baseAddress);

            _host.Credentials.ServiceCertificate.SetCertificate("CN=sMessenger", StoreLocation.CurrentUser, StoreName.TrustedPublisher);
            _host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;

            ServiceMetadataBehavior metadataBehavior = _host.Description.Behaviors.Find<ServiceMetadataBehavior>();
            if (metadataBehavior == null)
            {
                metadataBehavior = new ServiceMetadataBehavior();
                metadataBehavior.HttpGetEnabled = true;
                metadataBehavior.HttpGetUrl = _mexAddress;
                _host.Description.Behaviors.Add(metadataBehavior);
            }
            else
            {
                metadataBehavior.HttpGetEnabled = true;
                metadataBehavior.HttpGetUrl = _mexAddress;
            }
            _host.AddServiceEndpoint(typeof(IsMessengerServer), _binding, _address);

            _host.BeginOpen(new AsyncCallback(BeginOpenEnded), null);
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            btnStop.Enabled = false;
            _host.BeginClose(new AsyncCallback(BeginCloseEnded), null);

            _customResolver.BeginClose(null, null);
            _crs.Close();
        }

        private void BeginOpenEnded(IAsyncResult result)
        {
            _host.EndOpen(result);
            MethodInvoker invoker = delegate
            {
                btnStop.Enabled = true;
            };
            this.Invoke(invoker);

            // Open service resolver
            _crs = new CustomPeerResolverService();
            _crs.ControlShape = false;
            _customResolver = new ServiceHost(_crs);
            //_customResolver.Credentials.Peer.MessageSenderAuthentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
            //_customResolver.Credentials.Peer.PeerAuthentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
            //_customResolver.Credentials.ServiceCertificate.SetCertificate("CN=sMessenger", StoreLocation.CurrentUser, StoreName.TrustedPublisher);
            //_customResolver.Credentials.ClientCertificate.SetCertificate("CN=sMessenger", StoreLocation.CurrentUser, StoreName.TrustedPublisher);
            //_customResolver.Credentials.ClientCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
            
            _crs.Open();
            _customResolver.BeginOpen(ResolverOpenEnded, null);
        }

        private void BeginCloseEnded(IAsyncResult result)
        {
            _host.EndClose(result);
            MethodInvoker invoker = delegate
            {
                btnStart.Enabled = true;
            };
            this.Invoke(invoker);
        }

        private void ResolverOpenEnded(IAsyncResult result)
        {
            try
            {
                _customResolver.EndOpen(result);
            }
            catch (Exception e)
            {
                MessageBox.Show("Error: " + e.ToString());
                Application.Exit();
            }
        }
        
        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            if (_host != null)
                _host.Close();
            base.OnFormClosed(e);
        }

        #region IView Members

        public void AddToLog(string message)
        {
            MethodInvoker invoker = delegate
            {
                tbLog.AppendText(message + Environment.NewLine);
            };
            this.Invoke(invoker);
        }

        public void ClearLog()
        {
            MethodInvoker invoker = delegate
            {
                tbLog.Clear();
            };
            this.Invoke(invoker);
        }

        #endregion

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            ClearLog();
        }
    }
}
